package vm

import (
	"os"
	"strings"
	"kumachan/standalone/rx"
	"kumachan/interpreter/lang/common/source"
	. "kumachan/interpreter/runtime/def"
)


type InteropHandle struct {
	context   Context
	machine   *Machine
	location  *ExecutionLocation  // nil: top level
}

func (h InteropHandle) Call(v Value, arg Value) Value {
	var f, ok = v.(FuncValue)
	if ok {
		switch f := (*f).(type) {
		case UsualFunction:
			return call(h.context, h.machine, f, arg)
		case NativeFunction:
			return f(arg, h)
		default:
			panic("invalid function value")
		}
	} else {
		panic("cannot call a non-function value")
	}
}

func (h InteropHandle) CallDetached(ctx Context, f FuncValue, arg Value) Value {
	return h.machine.Call(ctx, f, arg)
}

func (h InteropHandle) Context() *rx.Context {
	return h.context
}
func (h InteropHandle) Location() (ExecutionLocation, bool) {
	if h.location != nil {
		return *(h.location), true
	} else {
		return ExecutionLocation {}, false
	}
}
func (h InteropHandle) Scheduler() rx.Scheduler {
	return h.machine.scheduler
}
func (h InteropHandle) Environment() *Environment {
	return h.machine.options.Environment
}
func (h InteropHandle) DebugOptions() DebugOptions {
	return h.machine.options.DebuggingOptions.BasicOptions
}
func (h InteropHandle) EntryModulePath() string {
	var raw = h.machine.program.Metadata.EntryModulePath
	return strings.TrimRight(raw, string([] rune { os.PathSeparator }))
}
func (h InteropHandle) KmdApi() KmdApi {
	return h.machine.kmdApi
}
func (h InteropHandle) RpcApi() RpcApi {
	return h.machine.rpcApi
}
func (h InteropHandle) Resource(kind string, path string) (source.Resource, bool) {
	var category = h.machine.resources[kind]
	var res, exists = category[path]
	return res, exists
}


